package com.example.demo.controller;

import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.audio.ttsv2.enrollment.Voice;
import com.alibaba.dashscope.audio.ttsv2.enrollment.VoiceEnrollmentService;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.example.demo.dto.ApiResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.example.demo.dto.ApiResponse;

@RestController
@RequestMapping("/api/tongyi/voice")
public class VoiceController {
    private static final String API_KEY = "sk-dbb9cbbf616a4be6abb779c0e00621c9"; // 替换为你的API-KEY
    private static final String PREFIX = "prefix"; // 可替换为任意标识符
    private static final String TARGET_MODEL = "cosyvoice-clone-v1";
    private static final String STATIC_URL_BASE = "http://8.154.32.215:80"; // 根URL

    @PostMapping("/synthesize")
    public ResponseEntity<ApiResponse<String>> synthesizeVoice(@RequestParam("audio") MultipartFile file,
                                                               @RequestParam("user_input") String text,
                                                               @RequestParam(value = "isclone", required = false) boolean isClone) {
        if (file.isEmpty() || text == null || text.isEmpty()) {
            return ResponseEntity.badRequest().body(ApiResponse.error("音频文件和文本内容不能为空"));
        }

        // 保存上传的音频文件到服务器静态资源文件夹
        String fileName = file.getOriginalFilename();
        String filePath = "/var/www/html/audiopath/" + fileName;
        File audioFile = new File(filePath);

        try (FileOutputStream fos = new FileOutputStream(audioFile)) {
            fos.write(file.getBytes());
        } catch (IOException e) {
            return ResponseEntity.internalServerError().body(ApiResponse.error("上传音频文件失败"));
        }

        // 构造可以通过HTTP访问的音频文件URL
        String fileUrl = STATIC_URL_BASE + "/audiopath/" + fileName;
        System.out.println("Your audio file URL is " + fileUrl);

        String voiceId;
        try {
            // 调用阿里大模型服务复刻声音
            VoiceEnrollmentService service = new VoiceEnrollmentService(API_KEY);
            Voice myVoice = service.createVoice(TARGET_MODEL, PREFIX, fileUrl);
            voiceId = myVoice.getVoiceId();
            System.out.println("Your voice ID is " + voiceId);
        } catch (NoApiKeyException | InputRequiredException e) {
            return ResponseEntity.internalServerError().body(ApiResponse.error("复刻声音失败: " + e.getMessage()));
        }

        // 使用复刻的声音合成文本为语音
        String outputFileName = fileName.split("\\.")[0] + "_output.mp3";
        String outputFilePath = "/var/www/html/audiopath/" + outputFileName;

        // 如果文件已存在，添加索引区分
        int index = 1;
        while (new File(outputFilePath).exists()) {
            outputFileName = fileName.split("\\.")[0] + "_output(" + index + ").mp3";
            outputFilePath = "/var/www/html/audiopath/" + outputFileName;
            index++;
        }

        try {
            SpeechSynthesisParam param = SpeechSynthesisParam.builder()
                    .apiKey(API_KEY)
                    .model(TARGET_MODEL)
                    .voice(voiceId)
                    .build();
            SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
            ByteBuffer audio = synthesizer.call(text);

            try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
                fos.write(audio.array());
            }
        } catch (IOException e) {
            return ResponseEntity.internalServerError().body(ApiResponse.error("保存合成音频文件失败"));
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body(ApiResponse.error("合成语音失败: " + e.getMessage()));
        }

        // 返回合成后的音频文件URL
        String fullUrl = STATIC_URL_BASE + "/audiopath/" + outputFileName;
        System.out.println("Your output file URL is: " + fullUrl);
        return ResponseEntity.ok(ApiResponse.success(fullUrl, "语音合成成功"));
    }
}
